<!--
 * @Author: Xujianchen
 * @Date: 2024-07-05 15:56:42
 * @LastEditors: xujianchen
 * @LastEditTime: 2024-07-06 14:42:30
 * @Description: 签名板
-->
<template>
  <div class="canvas-box">
    <canvas ref="canvasRef" crossOrigin="anoymous" :width="canvasWidth" :height="height" />
    <slot name="action">
      <div class="btn-box">
        <el-button @click="clear">清空</el-button>
        <el-button type="primary" @click="submit">保存</el-button>
      </div>
    </slot>
  </div>
</template>

<script setup>
import { ElMessage } from 'element-plus'

const props = defineProps({
  height: {
    type: [String, Number],
    default: 300,
  },
  lineWidth: {
    type: [String, Number],
    default: 3,
  },
})
const emit = defineEmits(['clear', 'save'])

const canvasRef = ref(null)
const hasDraw = ref(false)
const canvasWidth = ref(0)
const eventStart = 'ontouchstart' in document ? 'touchstart' : 'mousedown'
const eventMove = 'ontouchmove' in document ? 'touchmove' : 'mousemove'
const eventEnd = 'ontouchend' in document ? 'touchend' : 'mouseup'
let ctx

onMounted(() => initCanvas())

function initCanvas() {
  canvasWidth.value = document.querySelector('.canvas-box').clientWidth
  const canvasEl = canvasRef.value
  ctx = canvasEl.getContext('2d')
  let canvasMoveUse

  canvasEl.addEventListener(eventStart, (e) => {
    e.preventDefault()
    canvasMoveUse = true
    const startLeft = e.touches
      ? e.touches[0].clientX - canvasEl.getBoundingClientRect().left
      : e.offsetX || e.layerX
    const startTop = e.touches
      ? e.touches[0].clientY - canvasEl.getBoundingClientRect().top
      : e.offsetY || e.layerY
    ctx.lineWidth = +props.lineWidth
    ctx.beginPath()
    ctx.moveTo(startLeft, startTop)
  })

  canvasEl.addEventListener(
    eventMove,
    (e) => {
      if (canvasMoveUse) {
        e.preventDefault()
        hasDraw.value = true
        const startLeft = e.touches
          ? e.touches[0].clientX - canvasEl.getBoundingClientRect().left
          : e.offsetX || e.layerX
        const startTop = e.touches
          ? e.touches[0].clientY - canvasEl.getBoundingClientRect().top
          : e.offsetY || e.layerY
        ctx.lineTo(startLeft, startTop)
        ctx.stroke()
      }
    },
    false,
  )

  canvasEl.addEventListener(eventEnd, () => (canvasMoveUse = false))

  canvasEl.addEventListener('mouseleave', () => (canvasMoveUse = false))
}

function submit() {
  if (!hasDraw.value) {
    return ElMessage.warning('无内容')
  }
  emit('save', canvasRef.value.toDataURL())
}

function clear() {
  hasDraw.value = false
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
  emit('clear')
}
</script>

<style lang="scss" scoped>
canvas {
  background-color: var(--el-color-white);
  margin: $space-small 0;
  border: 1px solid var(--el-border-color);
  border-radius: 8px;
}
.btn-box {
  display: flex;
  justify-content: flex-end;
}
</style>
